/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2021-08-16 08:50:33
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-10-21 16:30:24
 * @Description: file content
 *
 * 若要改module和egg原来的service进行对调。就是module使用service，egg另外取名。
 * 则
 * 需修改interface IService
 * declareTo Context.service
 *
 * pattern 应该跟随config配置的modules.imports一起设置。才能实现功能和代码提示一致。实现只使用某些模块。
 *
 */
'use strict';
// const path = require('path');
// 引用egg-ts-helper 内部的，相当于替换默认auto的generator
// const classGen = require("egg-ts-helper/dist/generators/class").default

// 不用自定义生成器了。使用distName
// const genratorService = (config, baseConfig) => {
//   console.info(config);
//   console.info(config.fileList);
//   // console.info(baseConfig);

//   const dtsDir = path.join(config.dtsDir, 'service.d.ts');

//   config.interfaceHandle = config.interfaceHandle || 'AutoInstanceType<typeof {{ 0 }}>';

//   const result = classGen(config, baseConfig);
//   console.log(result);
//   // 替换掉默认的，自定义就是改这里而已。
//   result.dist = dtsDir;

//   /* istanbul ignore else */
//   if (result.content) {
//     result.content = [
//       'type AnyClass = new (...args: any[]) => any;',
//       'type AnyFunc<T = any> = (...args: any[]) => T;',
//       'type CanExportFunc = AnyFunc<Promise<any>> | AnyFunc<IterableIterator<any>>;',
//       'type AutoInstanceType<T, U = T extends CanExportFunc ? T : T extends AnyFunc ? ReturnType<T> : T> = U extends AnyClass ? InstanceType<U> : U;',
//       result.content,
//     ].join('\n');
//   }

//   return result;
// };

module.exports = (importsModules = []) => {
  const servicePattern = importsModules.length > 0 ? importsModules.map(mod => mod + '/**/*.service.(ts|js)') : '**/*.service.(ts|js)';
  const controllerPattern = importsModules.length > 0 ? importsModules.map(mod => mod + '/**/*.controller.(ts|js)') : '**/*.controller.(ts|js)';

  return {
    watchDirs: {
      moduleService: {
        directory: 'app/modules', // 监听目录
        pattern: servicePattern, // 遍历的文件表达式，一般都不需要改这个
        // ignore: '', // 指定忽略某些文件的表达式，默认为空
        generator: 'auto', // 生成器名称，取值为 class、auto、function、object
        // generator: genratorService, // 生成器名称，取值为 class、auto、function、object
        interface: 'IService', // interface 名称，如果不填的话，将会随机生成个 interface
        // declareTo: 'Context.service', // 指定定义到 egg 的某个类型下
        distName: 'service.d.ts', // 读源码发现可以传入此参数实现自定义声明文件名称。解决了问题，无需自定义。
        watch: true, // 是否需要监听文件改动
        caseStyle(pathItem) {
          // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
          pathItem = pathItem.replace(/.service$/, '');
          if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
            throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
          }
          pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
          const first = pathItem[0];
          return first.toLowerCase() + pathItem.substring(1);
        }, // 模块命名格式
        // interfaceHandle: val => `ReturnType<typeof ${val}>`, // interface 预处理方法
        // trigger: ['add', 'unlink'], // 当接收到这些文件更改事件的时候，会触发 d.ts 的重新生成, 所有事件: ['add', 'unlink', 'change']
      },
      // oldService: {
      //   directory: 'app/service', // 监听目录
      //   // pattern: servicePattern, // 遍历的文件表达式，一般都不需要改这个
      //   // ignore: '', // 指定忽略某些文件的表达式，默认为空
      //   generator: 'auto', // 生成器名称，取值为 class、auto、function、object
      //   // generator: genratorService, // 生成器名称，取值为 class、auto、function、object
      //   interface: 'IService', // interface 名称，如果不填的话，将会随机生成个 interface
      //   declareTo: 'Context.service', // 指定定义到 egg 的某个类型下
      //   distName: 'svs.d.ts', // 读源码发现可以传入此参数实现自定义声明文件名称。解决了问题，无需自定义。
      //   watch: true, // 是否需要监听文件改动
      //   caseStyle(pathItem) {
      //     // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
      //     //   pathItem = pathItem.replace(/.service$/, "");
      //     if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
      //       throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
      //     }
      //     pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
      //     const first = pathItem[0];
      //     return first.toLowerCase() + pathItem.substring(1);
      //   }, // 模块命名格式
      //   // interfaceHandle: val => `ReturnType<typeof ${val}>`, // interface 预处理方法
      //   // trigger: ['add', 'unlink'], // 当接收到这些文件更改事件的时候，会触发 d.ts 的重新生成, 所有事件: ['add', 'unlink', 'change']
      // },
      moduleController: {
        directory: 'app/modules', // 监听目录
        pattern: controllerPattern, // 遍历的文件表达式，一般都不需要改这个
        // ignore: '', // 指定忽略某些文件的表达式，默认为空
        generator: 'class', // 生成器名称，取值为 class、auto、function、object
        interface: 'IController', // interface 名称，如果不填的话，将会随机生成个 interface
        // declareTo: 'Application.controller_module', // 指定定义到 egg 的某个类型下 挂在IController上不是自定义的接口，所以不用再挂app
        distName: 'controller.d.ts',
        watch: true,
        caseStyle(pathItem) {
          // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
          pathItem = pathItem.replace(/.controller$/, '');
          if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
            throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
          }
          pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
          const first = pathItem[0];
          return first.toLowerCase() + pathItem.substring(1);
        }, // 模块命名格式
      },
      // 以下几个挂载是通过config配置customLoader实现，ets已内置对此支持，外部使用时如果重复生成，可以自行删除掉。
      // 常量自动挂载
      consts: {
        directory: 'app/consts', // 监听目录
        generator: 'object', // 生成器名称，取值为 class、auto、function、object
        interface: 'IEggAppConsts', // interface 名称，如果不填的话，将会随机生成个 interface
        declareTo: 'Application.consts', // 指定定义到 egg 的某个类型下 挂在IController上不是自定义的接口，所以不用再挂app
        distName: 'consts.d.ts',
        watch: true,
        caseStyle(pathItem) {
          // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
          if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
            throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
          }
          pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
          const first = pathItem[0];
          return first.toLowerCase() + pathItem.substring(1);
        }, // 模块命名格式
      },
      // 仓库逻辑封装，放数据存取逻辑
      repos: {
        directory: 'app/repos', // 监听目录
        generator: 'class', // 生成器名称，取值为 class、auto、function、object
        interface: 'IEggAppRepos', // interface 名称，如果不填的话，将会随机生成个 interface
        declareTo: 'Application.repos', // 指定定义到 egg 的某个类型下
        distName: 'repos.d.ts',
        watch: true,
        caseStyle(pathItem) {
          // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
          if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
            throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
          }
          pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
          const first = pathItem[0];
          return first.toLowerCase() + pathItem.substring(1);
        }, // 模块命名格式
      },
      // 功能， 纯业务逻辑，与请求上下文ctx无关地。
      functions: {
        directory: 'app/functions', // 监听目录
        generator: 'class', // 生成器名称，取值为 class、auto、function、object
        interface: 'IEggAppFunctions', // interface 名称，如果不填的话，将会随机生成个 interface
        declareTo: 'Application.functions', // 指定定义到 egg 的某个类型下
        distName: 'functions.d.ts',
        watch: true,
        caseStyle(pathItem) {
          // 此处逻辑必须跟自定义加载器中的caseStyle自定义方法相一致，否则生成的d.ts无法对应。
          if (!/^[a-z][a-z0-9_-]*$/i.test(pathItem)) {
            throw new Error(`${pathItem} is not match 'a-z0-9_-' in ${pathItem}`);
          }
          pathItem = pathItem.replace(/[_-][a-z]/gi, s => s.substring(1).toUpperCase());
          const first = pathItem[0];
          return first.toLowerCase() + pathItem.substring(1);
        }, // 模块命名格式
      },
    },
  };
};
